import org.apache.commons.lang3.time.DateFormatUtils;
import org.apache.commons.lang3.time.DateUtils;

import java.sql.Timestamp;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;

/**
 * @author wxp@jtang.cn
 */
public class DateUtil {
	public final static long ONE_DAY_TIME = 24 * 60 * 60 * 1000;
	public final static String FORMAT_SHORT = "yyyy-MM-dd";
	public final static String FORMAT_SHORT_CLEAN = "yyyyMMdd";
	public final static String FORMAT_LONG = "yyyy-MM-dd HH:mm:ss";
	public final static String FORMAT_LONG_CLEAN = "yyyyMMddHHmmss";
	public final static String FORMAT_FULL = "yyyy-MM-dd HH:mm:ss.SSS";
	public final static String FORMAT_FULL_CLEAN = "yyyyMMddHHmmssSSS";
	public final static String FORMAT_FULL_CLEAN_US = "yyyy-MM-dd HH:mm:ss.SSSSSS";
	public final static String FORMAT_SHORT_CN = "yyyy年MM月dd日";
	public final static String FORMAT_LONG_CN = "yyyy年MM月dd日 HH时mm分ss秒";
	public final static String FORMAT_FULL_CN = "yyyy年MM月dd日 HH时mm分ss秒SSS毫秒";

	public final static String FOMAT_MINUTES_CLEAN = "yyyyMMddHHmm";
	public final static String FORMAT_HOUR_CLEAN = "yyyyMMddHH";
	public final static String FORMAT_MONTH = "yyyy-MM";
	public final static String FORMAT_MONTH_CLEAN = "yyyyMM";
	public final static String FORMAT_YEAR = "yyyy";
	public final static String FORMAT_STORE_PATH = "yyyyMM/dd";

	public final static String FORMAT_MINUTE = "yyyyMMddHHmm";
	public final static String FORMAT_MINUTES_CLEAN = "yyyyMMddHHmm";
	public final static String FORMAT_NO_SECONDS = "yyyy-MM-dd HH:mm";
	public final static String FORMAT_NO_HOUR = "yyyy-MM-dd HH";

	public static String dateToString(Date date, String pattern) {
		try {
			return DateFormatUtils.format(date, pattern);
		} catch (Exception e) {
		}
		return null;
	}

	public static Date stringToDate(String date, String pattern) {
		try {
			return DateUtils.parseDate(date, new String[] { pattern });
		} catch (Exception e) {
		}
		return null;
	}

	public static Timestamp getTimestamp(Date date) {
		try {
			return new Timestamp(date.getTime());
		} catch (Exception e) {
		}
		return null;
	}

	public static int getAge(Date birthDay) {
		if (birthDay == null) {
			return -1;
		}
		Calendar cal = Calendar.getInstance();
		if (cal.before(birthDay)) {
			return -1;
		}
		int yearNow = cal.get(Calendar.YEAR);
		cal.setTime(birthDay);
		int yearBirth = cal.get(Calendar.YEAR);
		int age = yearNow - yearBirth;
		return age;
	}

	public static Date getStartDate(String startTime) {
		try {
			return new SimpleDateFormat(FORMAT_SHORT).parse(startTime);
		} catch (ParseException e) {
		}
		return null;
	}

	public static Date getEndDate(String endTime) {
		Date end = null;
		try {
			end = new SimpleDateFormat(FORMAT_SHORT).parse(endTime);
		} catch (ParseException e) {
		}
		if (end != null) {
			end = new Date(end.getTime() + ONE_DAY_TIME);
		}
		return null;
	}

	public static String getNextMonth(Date date) {
		SimpleDateFormat format = new SimpleDateFormat("yyyyMM");
		Calendar calendar = Calendar.getInstance();
		calendar.setTime(date);
		calendar.add(Calendar.MONTH, 1);
		return format.format(calendar.getTime());
	}

	public static String getPreMonth(Date date) {
		SimpleDateFormat format = new SimpleDateFormat("yyyyMM");
		Calendar calendar = Calendar.getInstance();
		calendar.setTime(date);
		calendar.add(Calendar.MONTH, -1);
		return format.format(calendar.getTime());
	}

	public static Date getNextYearSameDay(Date date) {
		Calendar calendar = Calendar.getInstance();
		calendar.setTime(date);
		int month = calendar.get(Calendar.MONTH);
		calendar.set(Calendar.MONTH, month + 12);
		// calendar.set(Calendar.DAY_OF_MONTH,
		// calendar.getActualMinimum(Calendar.DAY_OF_MONTH));
		return calendar.getTime();
	}

	public static Date getPreMonthFirstDay(Date date) {
		Calendar calendar = Calendar.getInstance();
		calendar.setTime(date);
		int month = calendar.get(Calendar.MONTH);
		calendar.set(Calendar.MONTH, month - 1);
		calendar.set(Calendar.DAY_OF_MONTH, calendar.getActualMinimum(Calendar.DAY_OF_MONTH));
		return calendar.getTime();
	}

	public static Date getMonthFirstDay(Date date) {
		Calendar calendar = Calendar.getInstance();
		calendar.setTime(date);
		// int month = calendar.get(Calendar.MONTH);
		// calendar.set(Calendar.MONTH, month - 1);
		calendar.set(Calendar.DAY_OF_MONTH, calendar.getActualMinimum(Calendar.DAY_OF_MONTH));
		return calendar.getTime();
	}

	public static Date getPreMonthLastDay(Date date) {
		Calendar calendar = Calendar.getInstance();
		calendar.setTime(date);
		int month = calendar.get(Calendar.MONTH);
		calendar.set(Calendar.MONTH, month - 1);
		calendar.set(Calendar.DAY_OF_MONTH, calendar.getActualMaximum(Calendar.DAY_OF_MONTH));
		return calendar.getTime();
	}

	public static Date getNextMonthFirstDay(Date date) {
		Calendar calendar = Calendar.getInstance();
		calendar.setTime(date);
		int month = calendar.get(Calendar.MONTH);
		calendar.set(Calendar.MONTH, month + 1);
		calendar.set(Calendar.DAY_OF_MONTH, calendar.getActualMinimum(Calendar.DAY_OF_MONTH));
		return calendar.getTime();
	}

	public static Date getNextMonthLastDay(Date date) {
		Calendar calendar = Calendar.getInstance();
		calendar.setTime(date);
		int month = calendar.get(Calendar.MONTH);
		calendar.set(Calendar.MONTH, month + 1);
		calendar.set(Calendar.DAY_OF_MONTH, calendar.getActualMaximum(Calendar.DAY_OF_MONTH));
		return calendar.getTime();
	}

	public static Date get2MonthLaterFirstDay(Date date) {
		Calendar calendar = Calendar.getInstance();
		calendar.setTime(date);
		int month = calendar.get(Calendar.MONTH);
		calendar.set(Calendar.MONTH, month + 2);
		calendar.set(Calendar.DAY_OF_MONTH, calendar.getActualMinimum(Calendar.DAY_OF_MONTH));
		return calendar.getTime();
	}

	public static Date fixTimeToMin(Date date) {
		Calendar calendar = Calendar.getInstance();
		calendar.setTime(date);
		calendar.set(Calendar.HOUR_OF_DAY, 0);
		calendar.set(Calendar.MINUTE, 0);
		calendar.set(Calendar.SECOND, 0);
		calendar.set(Calendar.MILLISECOND, 0);
		return calendar.getTime();
	}

	public static Date fixTimeToMax(Date date) {
		Calendar calendar = Calendar.getInstance();
		calendar.setTime(date);
		calendar.set(Calendar.HOUR_OF_DAY, 23);
		calendar.set(Calendar.MINUTE, 59);
		calendar.set(Calendar.SECOND, 59);
		calendar.set(Calendar.MILLISECOND, 999);
		return calendar.getTime();
	}
	
	public static List<Date> getDateList(Date startDate, Date endDate) {
		List<Date> dateList = new ArrayList<Date>();
		Calendar start = Calendar.getInstance();
		start.setTime(startDate);

		Calendar end = Calendar.getInstance();
		end.setTime(endDate);
		end.add(Calendar.DAY_OF_YEAR, 1);

		while (start.before(end)) {
			dateList.add(start.getTime());
			start.add(Calendar.DAY_OF_YEAR, 1);
		}
		return dateList;
	}
}
